#include "datamonitor.h"
#include "ui_datamonitor.h"
#include <QDateTime>
#include <QtCharts/QDateTimeAxis>
#include <QtCharts/QValueAxis>

// 构造函数
DataMonitor::DataMonitor(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::DataMonitor),
    timer(new QTimer(this)),
    temperatureSeries(new QLineSeries()),
    humiditySeries(new QLineSeries()),
    lightSeries(new QLineSeries()),
    chart(new QChart()),
    db(SQLiteDatabase::getInstance()), // 初始化 SQLiteDatabase 实例
    lastTimestamp(QDateTime::currentDateTime().addSecs(-72 * 3600).toMSecsSinceEpoch()) // 初始化为24小时前
{
    ui->setupUi(this);

    // 设置系列的名字
    temperatureSeries->setName("Temperature");
    humiditySeries->setName("Humidity");
    lightSeries->setName("Light");

    // 添加系列到图表
    chart->addSeries(temperatureSeries);
    chart->addSeries(humiditySeries);
    chart->addSeries(lightSeries);

    // 设置X轴
    QDateTimeAxis *axisX = new QDateTimeAxis;
    axisX->setFormat("yyyy-MM-dd hh:mm"); // 确保格式仅显示日期和时间
    axisX->setTitleText("Time");
    chart->addAxis(axisX, Qt::AlignBottom);

    // 设置Y轴
    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 100); // 设置Y轴范围
    axisY->setTitleText("Value");
    chart->addAxis(axisY, Qt::AlignLeft);

    // 将系列附加到轴上
    temperatureSeries->attachAxis(axisX);
    temperatureSeries->attachAxis(axisY);
    humiditySeries->attachAxis(axisX);
    humiditySeries->attachAxis(axisY);
    lightSeries->attachAxis(axisX);
    lightSeries->attachAxis(axisY);

    // 设置图表标题
    chart->setTitle("Real-time Data Monitor");
    ui->chartView->setChart(chart);

    // 设置表格
    ui->tableWidget->setColumnCount(4);
    ui->tableWidget->setHorizontalHeaderLabels({"Timestamp", "Temperature", "Humidity", "Light"});

    // 设置时间编辑器的初始值
    ui->startTimeEdit->setDateTime(QDateTime::currentDateTime().addSecs(-24 * 3600));
    ui->endTimeEdit->setDateTime(QDateTime::currentDateTime());

    // 连接查看历史数据按钮的信号到槽函数
    connect(ui->viewHistoryButton, &QPushButton::clicked, this, &DataMonitor::onViewHistoryButtonClicked);

    // 设置复选框初始状态为勾选
    ui->temperatureCheckBox->setChecked(true);
    ui->humidityCheckBox->setChecked(true);
    ui->lightCheckBox->setChecked(true);

    // 连接复选框信号到槽函数
    connect(ui->temperatureCheckBox, &QCheckBox::toggled, this, &DataMonitor::toggleTemperatureSeries);
    connect(ui->humidityCheckBox, &QCheckBox::toggled, this, &DataMonitor::toggleHumiditySeries);
    connect(ui->lightCheckBox, &QCheckBox::toggled, this, &DataMonitor::toggleLightSeries);

    // 连接导出CSV按钮的信号到槽函数
    connect(ui->exportCsvButton, &QPushButton::clicked, this, &DataMonitor::onExportCsvButtonClicked);

    // 初始化数据
    updateRealtimeData();

    // 定时器用于实时数据更新，每5秒更新一次
    connect(timer, &QTimer::timeout, this, &DataMonitor::updateRealtimeData);
    timer->start(5000);
}

// 析构函数
DataMonitor::~DataMonitor()
{
    delete ui;
}

// 设置当前设备ID
void DataMonitor::setCurrentDevice(int deviceId)
{
    timer->start(5000);
    currentDeviceId = deviceId;
    clearData(); // 清除表格和图表数据

    updateRealtimeData();
}

// 清除表格和图表数据
void DataMonitor::clearData()
{
    // 清除表格数据
    ui->tableWidget->setRowCount(0);
    processedTimestamps.clear();
    // 清除图表数据
    temperatureSeries->clear();
    humiditySeries->clear();
    lightSeries->clear();
}

// 更新实时数据
void DataMonitor::updateRealtimeData()
{
    // 获取最老和最新的时间戳
    qint64 oldestTimestamp = getOldestTimestamp();
    qint64 newestTimestamp = getNewestTimestamp();

    // 从数据库中读取自上次读取后新增的数据
    QString condition = QString("timestamp > datetime(%1, 'unixepoch') AND device_id = %2")
                            .arg(lastTimestamp / 1000).arg(currentDeviceId);
    //lastTimestamp 是一个以毫秒为单位的时间戳，通过除以1000将其转换为以秒为单位的时间戳。
    //datetime(1625079600, 'unixepoch') 将 1625079600 秒转换为可读的日期时间格式。

    QJsonArray result = db->read("data", condition);

    if (result.isEmpty()) {
        qDebug() << "No new data found";
        return;
    }


    QList<QPointF> temperaturePoints;
    QList<QPointF> humidityPoints;
    QList<QPointF> lightPoints;

    for (const QJsonValue &value : result) {
        QJsonObject obj = value.toObject();

        QString timestampString = obj["timestamp"].toString();
        QDateTime dateTime = QDateTime::fromString(timestampString, "yyyy-MM-dd HH:mm:ss");
        qint64 timestamp = dateTime.toMSecsSinceEpoch();

        // 更新 lastTimestamp 为最新的时间戳
        if (timestamp > lastTimestamp) {
            lastTimestamp = timestamp;
        }

        // 检查并转换数据类型
        qreal temperature = obj["temperature"].toString().toDouble();
        qreal humidity = obj["humidity"].toString().toDouble();
        qreal light = obj["light"].toString().toDouble();

        if (!processedTimestamps.contains(timestamp)) {
            qDebug()<<"有新的数据加入";
            processedTimestamps.insert(timestamp);

            // 添加数据点到临时列表中
            temperaturePoints.append(QPointF(timestamp, temperature));
            humidityPoints.append(QPointF(timestamp, humidity));
            lightPoints.append(QPointF(timestamp, light));

            // 更新表格
            int newRow = ui->tableWidget->rowCount();
            ui->tableWidget->insertRow(newRow);
            ui->tableWidget->setItem(newRow, 0, new QTableWidgetItem(dateTime.toString("yyyy-MM-dd HH:mm:ss")));
            ui->tableWidget->setItem(newRow, 1, new QTableWidgetItem(QString::number(temperature)));
            ui->tableWidget->setItem(newRow, 2, new QTableWidgetItem(QString::number(humidity)));
            ui->tableWidget->setItem(newRow, 3, new QTableWidgetItem(QString::number(light)));

            // 发出数据更新信号
            emit temperatureDataUpdated(temperature);
            emit humidityDataUpdated(humidity);
            emit lightDataUpdated(light);
        }
    }

    // 对数据点按时间戳排序
    std::sort(temperaturePoints.begin(), temperaturePoints.end(), [](const QPointF &a, const QPointF &b) {
        return a.x() < b.x();
    });
    std::sort(humidityPoints.begin(), humidityPoints.end(), [](const QPointF &a, const QPointF &b) {
        return a.x() < b.x();
    });
    std::sort(lightPoints.begin(), lightPoints.end(), [](const QPointF &a, const QPointF &b) {
        return a.x() < b.x();
    });

    // 将数据点添加到系列中
    temperatureSeries->append(temperaturePoints);
    humiditySeries->append(humidityPoints);
    lightSeries->append(lightPoints);

    // 动态更新X轴范围
    QDateTime startTime = QDateTime::fromMSecsSinceEpoch(oldestTimestamp);
    QDateTime endTime = QDateTime::fromMSecsSinceEpoch(newestTimestamp);

    // 确保只设置一次轴
    chart->removeAxis(chart->axisX());
    chart->removeAxis(chart->axisY());

    // 设置轴的范围和格式
    QDateTimeAxis *axisX = new QDateTimeAxis;
    axisX->setFormat("yyyy-MM-dd hh:mm"); // 确保格式仅显示日期和时间
    axisX->setTitleText("Time");
    axisX->setRange(startTime, endTime); // 动态设置X轴范围
    chart->addAxis(axisX, Qt::AlignBottom);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 100); // 设置Y轴范围
    axisY->setTitleText("Value");
    chart->addAxis(axisY, Qt::AlignLeft);

    // 将系列附加到轴上
    temperatureSeries->attachAxis(axisX);
    temperatureSeries->attachAxis(axisY);
    humiditySeries->attachAxis(axisX);
    humiditySeries->attachAxis(axisY);
    lightSeries->attachAxis(axisX);
    lightSeries->attachAxis(axisY);
}

// 导出CSV文件的槽函数
void DataMonitor::onExportCsvButtonClicked()
{
    QString fileName = QFileDialog::getSaveFileName(this, "Export Data", "", "CSV Files (*.csv)");
    if (fileName.isEmpty())
        return;
    //如果 fileName 为空（用户取消了保存操作），函数直接返回，不执行后续操作。
    QFile file(fileName);
    if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
        return;
// 创建 QTextStream 对象并关联文件
    QTextStream out(&file);
    // 写入表头
    for (int column = 0; column < ui->tableWidget->columnCount(); ++column) {
        out << ui->tableWidget->horizontalHeaderItem(column)->text();
        if (column != ui->tableWidget->columnCount() - 1)
            out << ",";
    }
    out << "\n";

    // 写入表格内容
    for (int row = 0; row < ui->tableWidget->rowCount(); ++row) {
        for (int column = 0; column < ui->tableWidget->columnCount(); ++column) {
            out << ui->tableWidget->item(row, column)->text();
            if (column != ui->tableWidget->columnCount() - 1)
                out << ",";
        }
        out << "\n";
    }
    file.close();
}

// 查看历史数据的槽函数
void DataMonitor::onViewHistoryButtonClicked()
{
    timer->stop();
    QDateTime startTime = ui->startTimeEdit->dateTime();
    QDateTime endTime = ui->endTimeEdit->dateTime();
    QString condition = QString("timestamp BETWEEN datetime('%1') AND datetime('%2') AND device_id = %3")
                            .arg(startTime.toString("yyyy-MM-dd HH:mm:ss"))
                            .arg(endTime.toString("yyyy-MM-dd HH:mm:ss"))
                            .arg(currentDeviceId);

    QJsonArray result = db->read("data", condition);
    if (result.isEmpty()) {
        qDebug() << "No data found for the selected time range";
        return;
    }

    // 清除表格和图表数据
    ui->tableWidget->setRowCount(0);
    temperatureSeries->clear();
    humiditySeries->clear();
    lightSeries->clear();

    QSet<qint64> existingTimestamps;
    QList<QPointF> temperaturePoints;
    QList<QPointF> humidityPoints;
    QList<QPointF> lightPoints;

    for (const QJsonValue &value : result) {
        QJsonObject obj = value.toObject();
        QString timestampString = obj["timestamp"].toString();
        QDateTime dateTime = QDateTime::fromString(timestampString, "yyyy-MM-dd HH:mm:ss");
        qint64 timestamp = dateTime.toMSecsSinceEpoch();

        qreal temperature = obj["temperature"].toString().toDouble();
        qreal humidity = obj["humidity"].toString().toDouble();
        qreal light = obj["light"].toString().toDouble();

        // if (!existingTimestamps.contains(timestamp)) {
            existingTimestamps.insert(timestamp);

            temperaturePoints.append(QPointF(timestamp, temperature));
            humidityPoints.append(QPointF(timestamp, humidity));
            lightPoints.append(QPointF(timestamp, light));

            int newRow = ui->tableWidget->rowCount();
            ui->tableWidget->insertRow(newRow);
            ui->tableWidget->setItem(newRow, 0, new QTableWidgetItem(dateTime.toString("yyyy-MM-dd HH:mm:ss")));
            ui->tableWidget->setItem(newRow, 1, new QTableWidgetItem(QString::number(temperature)));
            ui->tableWidget->setItem(newRow, 2, new QTableWidgetItem(QString::number(humidity)));
            ui->tableWidget->setItem(newRow, 3, new QTableWidgetItem(QString::number(light)));
        }
   // }

    temperatureSeries->append(temperaturePoints);
    humiditySeries->append(humidityPoints);
    lightSeries->append(lightPoints);

    // 动态更新X轴范围
    QDateTime oldestTimestamp = QDateTime::fromMSecsSinceEpoch(temperatureSeries->points().first().x());
    QDateTime newestTimestamp = QDateTime::fromMSecsSinceEpoch(temperatureSeries->points().last().x());

    chart->removeAxis(chart->axisX());
    chart->removeAxis(chart->axisY());

    QDateTimeAxis *axisX = new QDateTimeAxis;
    axisX->setFormat("yyyy-MM-dd hh:mm");
    axisX->setTitleText("Time");
    axisX->setRange(oldestTimestamp, newestTimestamp);
    chart->addAxis(axisX, Qt::AlignBottom);

    QValueAxis *axisY = new QValueAxis;
    axisY->setRange(0, 100);
    axisY->setTitleText("Value");
    chart->addAxis(axisY, Qt::AlignLeft);

    temperatureSeries->attachAxis(axisX);
    temperatureSeries->attachAxis(axisY);
    humiditySeries->attachAxis(axisX);
    humiditySeries->attachAxis(axisY);
    lightSeries->attachAxis(axisX);
    lightSeries->attachAxis(axisY);
}

// 切换温度系列的可见性
void DataMonitor::toggleTemperatureSeries(bool checked)
{
    temperatureSeries->setVisible(checked);
}

// 切换湿度系列的可见性
void DataMonitor::toggleHumiditySeries(bool checked)
{
    humiditySeries->setVisible(checked);
}

// 切换光照系列的可见性
void DataMonitor::toggleLightSeries(bool checked)
{
    lightSeries->setVisible(checked);
}

// 获取最老的时间戳
qint64 DataMonitor::getOldestTimestamp()
{
    QString condition = QString("device_id = %1 ORDER BY timestamp ASC LIMIT 1").arg(currentDeviceId);
    QJsonArray result = db->read("data", condition);

    if (!result.isEmpty()) {
        QJsonObject obj = result.first().toObject();
        QString timestampString = obj["timestamp"].toString();
        QDateTime dateTime = QDateTime::fromString(timestampString, "yyyy-MM-dd HH:mm:ss");// 将时间戳字符串解析为QDateTime对象
        // if(lastTimestamp > dateTime.toMSecsSinceEpoch())
        // {
        //     return lastTimestamp;
        // }
        return dateTime.toMSecsSinceEpoch();// 返回时间戳的毫秒数表示
    }
    return QDateTime::currentDateTime().addSecs(-24 * 3600).toMSecsSinceEpoch();
}

// 获取最新的时间戳
qint64 DataMonitor::getNewestTimestamp()
{
    QString condition = QString("device_id = %1 ORDER BY timestamp DESC LIMIT 1").arg(currentDeviceId);
    QJsonArray result = db->read("data", condition);

    if (!result.isEmpty()) {
        QJsonObject obj = result.first().toObject();
        QString timestampString = obj["timestamp"].toString();
        QDateTime dateTime = QDateTime::fromString(timestampString, "yyyy-MM-dd HH:mm:ss");
        return dateTime.toMSecsSinceEpoch();
    }
    return QDateTime::currentDateTime().toMSecsSinceEpoch();
}
